/**
 * scheme.h
 */

#ifndef __SCHEME_H__
#define __SCHEME_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>

#pragma pack(1)
typedef struct {
	char week;
	char hour;
	char minute;
	char second;
}WeekTime;
#pragma pack()

typedef struct Scheme {
	WeekTime startTime;
	WeekTime endTime;
	struct Scheme *pNext;
} Scheme;

/**
 * get current system time
 * @return
 *		WeekTime
 */
WeekTime getWeekTime(void);

/**
 * week time convert to second
 * @param
 *		time		input	week time
 * @return
 *		seconds
 */
static inline int weekTimeToSec(WeekTime time) {
	return time.week * 24 * 60 *60 + time.hour * 60 * 60 + time.minute * 60 + time.second;
}

/**
 * second convert week time
 * @param
 *		sec	input	seconds
 * @return
 *		week time
 */
WeekTime secToWeekTime(int sec);

/**
 * get Scheme second
 * @param
 *		pScheme	input	scheme pointer
 * @return
 *		seconds
 */
static inline int getSchemeSec(Scheme *pScheme) {
	return weekTimeToSec(pScheme->endTime) - weekTimeToSec(pScheme->startTime);
}

/**
 * get time in a scheme list continue second, because in list, may scheme will overload
 * @param
 *		time		input	week time
 *		pList		input	scheme list
 * @return
 *		continue second
 */
int getWeekTimeContSec(WeekTime time, Scheme *pList);

/**
 * get current in a scheme list continue second
 * @param
 *		pList		input	scheme list
 * @return
 *		continue second
 */
static inline int getCurrContSec(Scheme *pList) {
	return getWeekTimeContSec(getWeekTime(), pList);
}

/**
 * judge time whether in scheme
 * @param
 *		pScheme		input	scheme pointer
 *		time			input	week time
 * @return
 *		true when in scheme, else false
 */
static inline bool isInSchemeRange(Scheme *pScheme, WeekTime time) {
	int startSec = weekTimeToSec(pScheme->startTime);
	int endSec = weekTimeToSec(pScheme->endTime);
	int sec = weekTimeToSec(time);
	return startSec <= sec && sec < endSec;
}

/**
 * judge time whether in scheme list time range
 * @ param
 *		pList		input	scheme list head
 *		time		input	which time will be judge
 * @ return
 *		true when in range, else will be false
 */
bool isInSchemeListRange(Scheme *pList, WeekTime time);

/**
 * judge current time whether in scheme range
 * @param
 *		pScheme		input	scheme pointer
 * @return
 *		true when in range, else false
 */
static inline bool isCurrInSchemeRange(Scheme *pScheme) {
	return isInSchemeRange(pScheme, getWeekTime());
}

/**
 * judge current whether in scheme list time range
 * @ param
 *		pList		input	scheme list head
 * @ return
 *		true when in range, else will be false
 */
static inline bool isCurrInSchemeListRange(Scheme * pList) {
	return isInSchemeListRange(pList, getWeekTime());
}

/**
 * generate Scheme list from pBuff, will alloc memory Scheme for store WeekTime, and it's user's
 * responsible to release Scheme use freeSchemeList()
 * @param
 *		pBuff	input	buffer pointer
 * @return
 *		Scheme list pointer, NULL when error or no sche
 */
Scheme *allocSchemeList(char *pBuff);

/**
 * delete Scheme from list
 * @param
 *		pScheme	input	Scheme
 *		ppList		input	Scheme list
 */
void freeSchemeFromList(Scheme *pScheme, Scheme **ppList);

/**
 * delete Scheme list
 * @param
 *		pList		input	Scheme list
 */
void freeSchemeList(Scheme *pList);

#if 0	// don't use calloc num Scheme at once
/**
 * generate Scheme list from pBuff, will alloc memory num Scheme at once with calloc() for store WeekTime, and it's user's
 * responsible to release Scheme use freeSchemeList()
 * @param
 *		pBuff	input	buffer pointer
 * @return
 *		Scheme list pointer, NULL when error or no sche
 */
Scheme *allocSchemeList_num_calloc(char *pBuff);

/**
 * delete Scheme list with alloc num Scheme with calloc at once
 * @param
 *		pList		input	Scheme list
 */
static inline void freeSchemeList_num_calloc(Scheme *pList) {
	free(pList);	// calloc()
}
#endif

/**
 * get Scheme list need buffer size
 * @param
 *		input	pList		Scheme list
 * @return
 *		need buffer size, -1 when error
 */
int getSchemeListBuffSize(Scheme *pList);

/**
 * convert Scheme list to buffer
 * @param
 *		pBuff	input	buffer
 *		buffSize	input	input buffer size
 *		pSensor	input	Scheme pointer
 * @return
 *		converted Scheme buffer size, -1 when error
 */
int schemeListToBuff(char *pBuff, int buffSize, Scheme *pSensor); 

#ifdef __cplusplus
}
#endif

#endif	// __SCHEME_H__

